<template>
  <div ref="chartRef" class="chart-container" :style="{
    width: typeof width === 'number' ? `${width}px` : width,
    height: typeof height === 'number' ? `${height}px` : height,
  }"></div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, watch, onActivated } from "vue";
import * as echarts from "echarts";
import { debounce } from "@/utils/DebounceAndThrottle";
const props = defineProps({
  width: {
    type: [String, Number],
    default: "100%",
  },
  height: {
    type: [String, Number],
    default: "400px",
  },
  title: {
    type: String,
    default: "",
  },
  data: {
    type: Array,
    required: true,
  },
  isDonut: {
    type: Boolean,
    default: false,
  },
  showLabel: {
    type: Boolean,
    default: true,
  },
  showLegend: {
    type: Boolean,
    default: true,
  },
  showRawData: {
    type: Boolean,
    default: false,
  },
  responsive: {
    type: Boolean,
    default: true,
  },
  customColors: {
    type: Array,
    default: () => [
      "#409EFF", // Primary
      "#67C23A", // Success
      "#E6A23C", // Warning
      "#F56C6C", // Danger
      "#909399", // Info
      "#337ecc", // Primary Dark
      "#529b2e", // Success Dark
      "#b88230", // Warning Dark
      "#c45656", // Danger Dark
      "#73767a", // Info Dark
    ],
  },
  unit: {
    type: String,
    default: '',
  },
  showDownload: {
    type: Boolean,
    default: true,
  },
  showValue: {
    type: Boolean,
    default: false,
  },
});

const colorPalette = computed(() => props.customColors);
const chartRef = ref(null);
let chart = null;
let resizeObserver = null;
let isResizing = false;

// 强制重绘函数
const forceResize = () => {
  if (chart) {
    setTimeout(() => {
      const currentAnimation = chart.getOption().animation;
      chart.setOption({
        animation: false
      });
      chart.resize();
      chart.setOption({
        animation: currentAnimation
      });
    }, 50);
  }
};

// 创建 resize 处理函数
const handleResize = debounce(() => {
  if (chart && !isResizing) {
    isResizing = true;
    forceResize();
    isResizing = false;
  }
}, 1000);

const commonConfig = computed(() => ({
  backgroundColor: "transparent",
  color: colorPalette.value,
  animation: true,
  animationDuration: 300,
  animationEasing: "cubicInOut",
  animationThreshold: 1500,
  progressiveThreshold: 2000,
  progressive: 150,
  hoverLayerThreshold: 2000,
}));

const getChartLayout = computed(() => {
  if (props.showLegend) {
    return {
      center: ["40%", "50%"],
      radius: props.isDonut ? ["40%", "65%"] : "55%",
    };
  } else {
    return {
      center: ["50%", "50%"],
      radius: props.isDonut ? ["45%", "75%"] : "65%",
    };
  }
});

const totalValue = computed(() => {
  return props.data.reduce((sum, item) => sum + item.value, 0);
});

const getPercentage = (value) => {
  return ((value / totalValue.value) * 100).toFixed(1);
};

const processedData = computed(() => {
  const total = props.data.reduce((sum, item) => sum + item.value, 0);
  return props.data.map(item => {
    const percentage = (item.value / total) * 100;
    return {
      ...item,
      label: {
        show: props.showLabel && percentage >= 1
      },
      labelLine: {
        show: props.showLabel && percentage >= 1
      }
    };
  });
});

const chartOption = computed(() => ({
  ...commonConfig.value,
  toolbox: props.showDownload ? {
    show: true,
    feature: {
      saveAsImage: {
        type: 'png',
        title: '保存为图片',
        pixelRatio: 2,
        backgroundColor: '#fff'
      }
    },
    right: '10px',
    top: '0px'
  } : null,
  title: props.title ? {
    text: props.title,
    textStyle: {
      fontSize: 16,
      fontWeight: "normal",
    },
    left: '20px'
  } : null,
  tooltip: {
    trigger: "item",
    formatter: (params) => {
      if (props.showRawData) {
        return `${params.name}: ${params.value} ${props.unit}`;
      }
      if (props.showValue) {
        return `${params.name}: ${params.value}`;
      }
      return `${params.name}: ${getPercentage(params.value)}%`;
    },
    textStyle: { fontSize: 12 },
    padding: [8, 12],
    borderRadius: 4,
    borderWidth: 0,
    backgroundColor: "rgba(255, 255, 255, 0.9)",
    shadowColor: "rgba(0, 0, 0, 0.1)",
    shadowBlur: 10,
    transitionDuration: 0.4,
  },
  legend: props.showLegend ? {
    show: true,
    orient: 'vertical',
    right: '20px',
    bottom: '20px',
    textStyle: {
      fontSize: 12,
    },
    itemWidth: 8,
    itemHeight: 8,
    itemGap: 15,
    type: 'scroll',
    pageTextStyle: {
      color: '#666'
    },
    icon: 'circle',
    formatter: (name) => {
      const data = props.data.find(item => item.name === name);
      if (!data) return name;

      if (props.showRawData) {
        return `${name} (${data.value}${props.unit})`;
      }
      if (props.showValue) {
        return `${name} (${data.value})`;
      }
      return `${name} (${getPercentage(data.value)}%)`;
    }
  } : null,
  series: [
    {
      name: props.title,
      type: "pie",
      ...getChartLayout.value,
      data: processedData.value,
      label: {
        fontSize: 12,
        formatter: (params) => {
          if (props.showRawData) {
            return `${params.name}: ${params.value} ${props.unit}`;
          }
          if (props.showValue) {
            return `${params.name}: ${params.value}`;
          }
          return `${params.name}: ${getPercentage(params.value)}%`;
        },
        alignTo: 'labelLine',
        edgeDistance: '0%',
        distanceToLabelLine: 5,
      },
      labelLine: {
        length: 10,
        length2: 15,
        smooth: true,
        lineStyle: {
          type: 'dashed',
          dashOffset: 2,
          dashArray: [4, 2],
        },
        maxSurfaceAngle: 80
      },
      labelLayout: {
        hideOverlap: true,
        moveOverlap: 'shiftY'
      },
      itemStyle: {
        borderRadius: 5,
        borderWidth: 2,
      },
      emphasis: {
        itemStyle: {
          shadowBlur: 10,
          shadowOffsetX: 0,
          shadowColor: "rgba(0, 0, 0, 0.5)",
        },
      },
      animationDuration: 300,
      animationEasing: "cubicInOut",
    },
  ],
}));

const initChart = () => {
  if (chart) {
    chart.dispose();
  }

  if (chartRef.value) {
    chart = echarts.init(chartRef.value, null, { renderer: "svg" });
    chart.setOption(chartOption.value);

    if (props.responsive) {
      resizeObserver = new ResizeObserver(handleResize);
      resizeObserver.observe(chartRef.value);
      window.addEventListener("resize", handleResize);
    }
  }
};

// 添加对 showLabel 的专门监听
watch(
  () => props.showLabel,
  () => {
    if (chart) {
      chart.clear();
      chart.setOption(chartOption.value);
    }
  }
);

// 监听其他属性变化
watch(
  () => [
    props.data,
    props.isDonut,
    props.title,
    props.showLegend,
    props.customColors,
    props.unit,
    props.showRawData,
  ],
  () => {
    chart?.setOption(chartOption.value);
  },
  { deep: true }
);

onMounted(() => {
  initChart();
});

onUnmounted(() => {
  if (resizeObserver) {
    resizeObserver.disconnect();
    resizeObserver = null;
  }
  window.removeEventListener("resize", handleResize);
  chart?.dispose();
});

onActivated(() => {
  if (chart) {
    forceResize();
  }
});
</script>

<style scoped>
.chart-container {
  position: relative;
  min-height: 200px;
}
</style>